home *** CD-ROM | disk | FTP | other *** search
/ Hottest 6 / Hottest 6 (1996)(PDSoft)[!].iso / software / emulators / frodo_1.5 / src / 1541.asm next >
Assembly Source File  |  1978-11-24  |  35KB  |  1,755 lines

  1. *
  2. * 1541.asm - 1541-Emulation, Dateihandling
  3. *
  4. * Copyright (C) 1994-1995 by Christian Bauer
  5. *
  6.  
  7. *
  8. * Anmerkungen:
  9. * ------------
  10. *
  11. * Aufrufkonventionen:
  12. *  - Die Routinen IECOut#? und IECIn geben in d0 den Status zurück.
  13. *    Dieser wird von den aufrufenden Routinen mit dem C64-Statusbyte
  14. *    ($90) verodert.
  15. *  - Die Routinen dürfen nur d0-d1/a0-a1 verändern
  16. *
  17. * Funktionsweise:
  18. *  - Am IEC-Bus gibt es drei Sorten von Geräten: Controller, Listener
  19. *    und Talker. Der Controller sind immer wir, zusätzlich können wir
  20. *    wahlweise Talker und Listener sein. Es kann immer nur einen Talker
  21. *    und einen Listener geben (am echten IEC-Bus sind mehrere Listener
  22. *    erlaubt, aber hier nicht).
  23. *  - Die Geräte, die angesprochen werden, sind entweder real am IEC-Kabel
  24. *    oder werden hier emuliert. Für jedes emulierte Laufwerk existiert
  25. *    eine eigene Datenstruktur (Drv?Data). Ein Zeiger darauf wird bei
  26. *    Talk/Listen in TalkerData/ListenerData gespeichert und steht den
  27. *    nachfolgend aufgerufenen Routinen zur Verfügung, damit sich diese
  28. *    um das jeweils angesprochene Laufwerk kümmern.
  29. *  - Bei Geräten am Kabel wird #?Data nicht benutzt, da die Routinen
  30. *    dann die Daten im wesentlichen einfach an den IEC-Bus durchreichen
  31. *
  32. * EOI/EOF:
  33. *  - Im Gegensatz zum Amiga, wo der EOF-Zustand erst nach dem Lesen
  34. *    des letzten Bytes erkannt wird, wird beim IEC-Bus das EOF
  35. *    gleichzeitig mit dem letzten Byte gesendet. Daher verwenden die
  36. *    Leseroutinen einen Puffer, in dem immer ein Byte bereitsteht.
  37. *
  38. * Directory-Emulation:
  39. *  - Wird das Directory geöffnet (Dateiname "$"), wird in T: eine
  40. *    temporäre Datei angelegt, die vom Aufbau genau einem 1541-Directory
  41. *    entspricht und diese Datei geöffnet. Sie kann dann mit den ganz
  42. *    normalen Lesebefehlen verarbeitet werden.
  43. *
  44. * Inkompatibilitäten/Verbesserungen:
  45. *  - Es kann nur ein Listener gleichzeitig aktiv sein
  46. *  - Kein Kommandokanal implementiert
  47. *  - Beim Empfang des Dateinamens sollte er auf Pufferüberlauf prüfen
  48. *
  49.  
  50.         MACHINE    68020
  51.  
  52.         INCLUDE    "exec/types.i"
  53.         INCLUDE    "exec/macros.i"
  54.         INCLUDE    "dos/dos.i"
  55.         INCLUDE    "dos/dosasl.i"
  56.         INCLUDE    "resources/misc.i"
  57.         INCLUDE    "hardware/cia.i"
  58.  
  59.         XREF    _SysBase
  60.         XREF    _DOSBase
  61.         XREF    _CiaBase
  62.         XREF    _MiscBase
  63.  
  64.         XREF    _ciaaprb
  65.         XREF    _ciaaddrb
  66.  
  67.         XDEF    Open1541
  68.         XDEF    Close1541
  69.         XDEF    ChangedDirs
  70.         XDEF    CloseIEC
  71.         XDEF    ChangedIEC
  72.         XDEF    IECOut
  73.         XDEF    IECOutATN
  74.         XDEF    IECOutSec
  75.         XDEF    IECIn
  76.         XDEF    IECSetATN
  77.         XDEF    IECRelATN
  78.         XDEF    IECTurnaround
  79.         XDEF    IECRelease
  80.         XDEF    IECIsOpen
  81.  
  82.         XDEF    Dir8        ;Prefs
  83.         XDEF    Dir9
  84.         XDEF    Dir10
  85.         XDEF    Dir11
  86.         XDEF    Drv8IsIEC
  87.         XDEF    Drv9IsIEC
  88.         XDEF    Drv10IsIEC
  89.         XDEF    Drv11IsIEC
  90.         XDEF    OtherIEC
  91.         XDEF    MapSlash
  92.  
  93.         SECTION    "CODE",CODE
  94.  
  95.  
  96. **
  97. ** Definitionen
  98. **
  99.  
  100. ; Datenstruktur für ein Laufwerk
  101.  STRUCTURE DRVDATA,0
  102.     BYTE    drv_ErrorCode        ;Letzter Fehlercode (ERR_#?)
  103.     BYTE    drv_ReadBuf        ;Byte-Puffer zum Lesen aus Dateien
  104.     BYTE    drv_IsIEC        ;Laufwerk wird über IEC-Kabel angesprochen
  105.     BYTE    pad0
  106.     STRUCT    drv_Handles,16*4    ;FileHandles für alle 16 Sekundäradressen
  107.     APTR    drv_NamePtr        ;Zeiger in Dateinamen, für Open/IECOut
  108.     APTR    drv_ErrorPtr        ;Zeiger in Fehlermeldung
  109.     APTR    drv_Lock        ;Lock des Verzeichnisses des Laufwerks
  110.  LABEL drv_SIZEOF
  111.  
  112. ; Register (müssen mit den Definitionen in 6510.asm übereinstimmen!)
  113. RAMPTR        EQUR    a4    ;Zeiger auf C64-RAM
  114.  
  115. ; C64-Status-Codes
  116. ST_OK        = 0    ;Alles klar
  117. ST_READ_TIMEOUT    = $02    ;Timeout beim Lesen
  118. ST_TIMEOUT    = $03    ;Timeout
  119. ST_EOF        = $40    ;End of file
  120. ST_NOTPRESENT    = $80    ;Device not present
  121.  
  122. ; IEC-Befehlscodes
  123. CMD_DATA    = $60
  124. CMD_CLOSE    = $e0
  125. CMD_OPEN    = $f0
  126.  
  127. ; Fehlercodes (genauer: Die Nummer des zugeh. Fehlertextes)
  128. ERR_OK        = 0    ;00: OK
  129. ERR_STARTUP    = 1    ;Einschaltmeldung
  130. ERR_FILENOTFOUND = 2    ;62: FILE NOT FOUND
  131. ERR_NOCHANNEL    = 3    ;70: NO CHANNEL
  132. ERR_SYNTAX33    = 4    ;33: SYNTAX ERROR (Wildcards beim Schreiben)
  133.  
  134. ; Makros für IEC-Kabel
  135. DATA_HI        MACRO
  136.         bclr    #5,_ciaaprb
  137.         ENDM
  138.  
  139. DATA_LO        MACRO
  140.         bset    #5,_ciaaprb
  141.         ENDM
  142.  
  143. CLOCK_HI    MACRO
  144.         bclr    #4,_ciaaprb
  145.         ENDM
  146.  
  147. CLOCK_LO    MACRO
  148.         bset    #4,_ciaaprb
  149.         ENDM
  150.  
  151. ATN_HI        MACRO
  152.         bclr    #3,_ciaaprb
  153.         ENDM
  154.  
  155. ATN_LO        MACRO
  156.         bset    #3,_ciaaprb
  157.         ENDM
  158.  
  159. LINE_RELEASE    MACRO
  160.         ATN_HI
  161.         bsr    Wait40us
  162.         CLOCK_HI
  163.         DATA_HI
  164.         ENDM
  165.  
  166. ; Data -> Carry, Clock -> Negative
  167. GET_DATA_CLOCK    MACRO
  168. \@1$        move.b    _ciaaprb,d0
  169.         cmp.b    _ciaaprb,d0
  170.         bne    \@1$
  171.         add.b    d0,d0
  172.         ENDM
  173.  
  174. WAIT_CLOCK_HI    MACRO
  175. \@1$        GET_DATA_CLOCK
  176.         bpl    \@1$
  177.         ENDM
  178.  
  179. WAIT_CLOCK_LO    MACRO
  180. \@1$        GET_DATA_CLOCK
  181.         bmi    \@1$
  182.         ENDM
  183.  
  184. WAIT_DATA_HI    MACRO
  185. \@1$        GET_DATA_CLOCK
  186.         bcc    \@1$
  187.         ENDM
  188.  
  189. WAIT_DATA_LO    MACRO
  190. \@1$        GET_DATA_CLOCK
  191.         bcs    \@1$
  192.         ENDM
  193.  
  194.  
  195. **
  196. ** 1541-Emulation starten
  197. **
  198.  
  199. ; Einschaltmeldung bereitstellen
  200. Open1541    move.b    #ERR_STARTUP,Drv8Data+drv_ErrorCode
  201.         move.b    #ERR_STARTUP,Drv9Data+drv_ErrorCode
  202.         move.b    #ERR_STARTUP,Drv10Data+drv_ErrorCode
  203.         move.b    #ERR_STARTUP,Drv11Data+drv_ErrorCode
  204.  
  205. ; Locks der Verzeichnisse holen
  206.         move.l    _DOSBase,a6
  207.         bra    OpenLocks
  208.  
  209.  
  210. **
  211. ** 1541-Emulation beenden
  212. **
  213.  
  214. ; Alle Dateien schließen
  215. Close1541    move.l    _DOSBase,a6
  216.  
  217.         lea    Drv8Data+drv_Handles,a2
  218.         bsr    FreeHandles
  219.         lea    Drv9Data+drv_Handles,a2
  220.         bsr    FreeHandles
  221.         lea    Drv10Data+drv_Handles,a2
  222.         bsr    FreeHandles
  223.         lea    Drv11Data+drv_Handles,a2
  224.         bsr    FreeHandles
  225.  
  226. ; Alle Locks freigeben
  227.         bsr    FreeLocks
  228.  
  229. ; Temporäre Datei löschen
  230.         move.l    #TempFileName,d1
  231.         JMPLIB    DeleteFile
  232.  
  233. FreeHandles    moveq    #15,d7        ;16 Kanäle
  234. 2$        move.l    (a2)+,d1
  235.         beq    1$
  236.         clr.l    -4(a2)        ;FileHandle löschen
  237.         JSRLIB    Close
  238. 1$        dbra    d7,2$
  239.         rts
  240.  
  241.  
  242. **
  243. ** Die Verzeichnisse haben sich geändert: Neue Locks holen
  244. **
  245.  
  246. ChangedDirs    move.l    _DOSBase,a6
  247.         bsr    FreeLocks
  248.         bra    OpenLocks
  249.  
  250.  
  251. **
  252. ** IEC-Einstellungen wurden verändert
  253. ** Rückgabe: d0=0 Alles OK
  254. **           d0=1 Parallelport belegt
  255. **           d0=2 Kein Timer frei
  256. **
  257.  
  258. ; Einstellungen übertragen
  259. ChangedIEC    moveq    #0,d1
  260.         move.w    Drv8IsIEC,d0
  261.         or.b    d0,d1
  262.         move.b    d0,Drv8Data+drv_IsIEC
  263.         move.w    Drv9IsIEC,d0
  264.         or.b    d0,d1
  265.         move.b    d0,Drv9Data+drv_IsIEC
  266.         move.w    Drv10IsIEC,d0
  267.         or.b    d0,d1
  268.         move.b    d0,Drv10Data+drv_IsIEC
  269.         move.w    Drv11IsIEC,d0
  270.         or.b    d0,d1
  271.         move.b    d0,Drv11Data+drv_IsIEC
  272.         or.w    OtherIEC,d1
  273.  
  274. ; IEC öffnen, wenn mindestens ein Gerät mit IEC laufen soll,
  275. ; sonst schließen
  276.         tst.b    d1
  277.         beq    CloseIEC
  278.         bra    OpenIEC
  279.  
  280.  
  281. **
  282. ** Auf Benutzung des IEC-Kabels vorbereiten
  283. ** Rückgabe: d0=0 Alles OK
  284. **           d0=1 Parallelport belegt
  285. **           d0=2 Kein Timer frei
  286. **
  287.  
  288. OpenIEC        move.l    a6,-(sp)
  289.         tst.b    IECIsOpen    ;Kann auch mehrmals aufgerufen werden
  290.         bne    OIECOK
  291.  
  292. ; Parallelport belegen
  293.         move.l    _MiscBase,a6
  294.         moveq    #MR_PARALLELPORT,d0
  295.         lea    ParPortName,a1
  296.         JSRLIB    AllocMiscResource
  297.         tst.l    d0
  298.         bne    OIECNoPort
  299.  
  300.         move.b    #$00,_ciaaprb    ;Port inaktiv
  301.         move.b    #$38,_ciaaddrb    ;DDR konfigurieren
  302.  
  303. ; Timer A belegen
  304.         move.l    _CiaBase,a6
  305.         lea    TimerInterrupt,a1
  306.         moveq    #CIAICRB_TA,d0
  307.         JSRLIB    AddICRVector
  308.         tst.l    d0
  309.         bne    1$
  310.  
  311. ; Gelungen
  312.         move.b    #CIAICRB_TA,WhichTimer
  313.         move.b    #CIAICRF_TA,WhichTimerMask
  314.         move.l    #$bfe401,CiaTimerReg
  315.         move.l    #$bfee01,CiaControlReg
  316.         bra    3$
  317.  
  318. ; Nicht gelungen, dann Timer B probieren
  319. 1$        lea    TimerInterrupt,a1
  320.         moveq    #CIAICRB_TB,d0
  321.         JSRLIB    AddICRVector
  322.         tst.l    d0
  323.         bne    2$
  324.  
  325. ; Gelungen
  326.         move.b    #CIAICRB_TB,WhichTimer
  327.         move.b    #CIAICRF_TB,WhichTimerMask
  328.         move.l    #$bfe601,CiaTimerReg
  329.         move.l    #$bfef01,CiaControlReg
  330.         bra    3$
  331.  
  332. ; Nicht gelungen, dann Parallelport wieder freigeben
  333. 2$        move.b    #$00,_ciaaddrb    ;Port auf Eingabe
  334.  
  335.         move.l    _MiscBase,a6
  336.         moveq    #MR_PARALLELPORT,d0
  337.         JSRLIB    FreeMiscResource
  338.  
  339.         moveq    #2,d0        ;Kein Timer frei
  340.         move.l    (sp)+,a6
  341.         rts
  342.  
  343. ; Alles klar, Timer-Interrupt abschalten und Timer stoppen
  344. 3$        move.b    WhichTimerMask,d0
  345.         JSRLIB    AbleICR
  346.  
  347.         move.l    CiaControlReg,a0
  348.         and.b    #$80,(a0)
  349.  
  350.         st.b    IECIsOpen
  351. OIECOK        moveq    #0,d0        ;Alles OK
  352.         move.l    (sp)+,a6
  353.         rts
  354.  
  355. OIECNoPort    moveq    #1,d0        ;Parallelport belegt
  356.         move.l    (sp)+,a6
  357.         rts
  358.  
  359.  
  360. **
  361. ** Benutzung des IEC-Kabels beenden
  362. ** Rückgabe: d0=0
  363. **
  364.  
  365. CloseIEC    tst.b    IECIsOpen
  366.         beq    1$
  367.  
  368.         move.b    #$00,_ciaaddrb    ;Port auf Eingabe
  369.  
  370.         move.l    a6,-(sp)    ;Parallelport freigeben
  371.         move.l    _MiscBase,a6
  372.         moveq    #MR_PARALLELPORT,d0
  373.         JSRLIB    FreeMiscResource
  374.  
  375.         move.l    CiaControlReg,a0 ;Timer stoppen
  376.         and.b    #$80,(a0)
  377.  
  378.         move.l    _CiaBase,a6
  379.         lea    TimerInterrupt,a1
  380.         move.b    WhichTimer,d0
  381.         JSRLIB    RemICRVector
  382.  
  383.         move.l    (sp)+,a6
  384.         clr.b    IECIsOpen
  385.  
  386. 1$        moveq    #0,d0
  387.         rts
  388.  
  389.  
  390. *
  391. * Locks freigeben
  392. *
  393.  
  394. FreeLocks    move.l    Drv8Data+drv_Lock,d1
  395.         beq    1$
  396.         JSRLIB    UnLock
  397. 1$        move.l    Drv9Data+drv_Lock,d1
  398.         beq    2$
  399.         JSRLIB    UnLock
  400. 2$        move.l    Drv10Data+drv_Lock,d1
  401.         beq    3$
  402.         JSRLIB    UnLock
  403. 3$        move.l    Drv11Data+drv_Lock,d1
  404.         beq    4$
  405.         JSRLIB    UnLock
  406. 4$        rts
  407.  
  408. *
  409. * Locks holen
  410. *
  411.  
  412. OpenLocks    move.l    #Dir8,d1
  413.         move.l    #ACCESS_READ,d2
  414.         JSRLIB    Lock
  415.         move.l    d0,Drv8Data+drv_Lock
  416.  
  417.         move.l    #Dir9,d1
  418.         move.l    #ACCESS_READ,d2
  419.         JSRLIB    Lock
  420.         move.l    d0,Drv9Data+drv_Lock
  421.  
  422.         move.l    #Dir10,d1
  423.         move.l    #ACCESS_READ,d2
  424.         JSRLIB    Lock
  425.         move.l    d0,Drv10Data+drv_Lock
  426.  
  427.         move.l    #Dir11,d1
  428.         move.l    #ACCESS_READ,d2
  429.         JSRLIB    Lock
  430.         move.l    d0,Drv11Data+drv_Lock
  431.         rts
  432.  
  433.  
  434. **
  435. ** IECOut - Ein Byte ausgeben
  436. ** d0.b: Byte
  437. ** d1.b: <0: EOI-Flag
  438. **
  439.  
  440. IECOut        tst.b    ListenerIsIEC    ;Listener am IEC-Kabel?
  441.         bne    IECByteOut    ;Ja, dann Byte über Kabel senden
  442.         tst.b    ListenerActive    ;Wurde ein Gerät angesprochen?
  443.         beq    1$
  444.  
  445.         cmp.b    #CMD_OPEN,ReceivedCmd
  446.         beq    OpenOut
  447.         cmp.b    #CMD_DATA,ReceivedCmd
  448.         beq    DataOut
  449.  
  450. 1$        move.b    #ST_TIMEOUT,d0    ;Kein Listener aktiv oder kein gültiger Befehl
  451.         rts
  452.  
  453.  
  454. **
  455. ** IECOutATN - Ein Byte mit ATN ausgeben (Talk/Listen/Untalk/Unlisten)
  456. ** d0.b: Byte
  457. **
  458.  
  459. IECOutATN    clr.b    SecAddr        ;Befehl kommt mit der Sekundäradresse danach
  460.         clr.b    ReceivedCmd
  461.  
  462.         move.b    d0,d1
  463.         and.b    #$0f,d0        ;d0.b: Gerätenummer
  464.         and.b    #$f0,d1        ;d1.b: Funktion
  465.  
  466.         st.b    Listening    ;Funktion auswerten
  467.         cmp.b    #$20,d1        ;Bei Listen ist das Flag Listening gesetzt
  468.         beq    Listen
  469.         clr.b    Listening
  470.         cmp.b    #$30,d1
  471.         beq    Unlisten
  472.         cmp.b    #$40,d1
  473.         beq    Talk
  474.         cmp.b    #$50,d1
  475.         beq    Untalk
  476.  
  477.         move.b    #ST_TIMEOUT,d0    ;Ungültige Funktion
  478.         rts
  479.  
  480.  
  481. **
  482. ** IECOutSec - Sekundäradresse ausgeben
  483. ** d0.b: Sekundäradresse
  484. **
  485.  
  486. IECOutSec    tst.b    Listening    ;Nach Listen oder nach Talk?
  487.         beq    1$
  488.  
  489.         tst.b    ListenerIsIEC    ;Nach Listen: Listener am IEC-Kabel?
  490.         bne    IECByteOutSec
  491.         tst.b    ListenerActive    ;Wurde ein Gerät angesprochen?
  492.         beq    2$
  493.  
  494.         move.b    d0,d1
  495.         and.b    #$0f,d0        ;Sekundäradresse
  496.         move.b    d0,SecAddr
  497.         and.b    #$f0,d1        ;und Befehlscode speichern
  498.         move.b    d1,ReceivedCmd
  499.         bra    SecListen    ;Sek.adr nach Listen
  500.  
  501. 1$        tst.b    TalkerIsIEC    ;Nach Talk: Talker am IEC-Kabel?
  502.         bne    IECByteOutSec
  503.         tst.b    TalkerActive    ;Wurde ein Gerät angesprochen?
  504.         beq    2$
  505.  
  506.         move.b    d0,d1
  507.         and.b    #$0f,d0        ;Sekundäradresse
  508.         move.b    d0,SecAddr
  509.         and.b    #$f0,d1        ;und Befehlscode speichern
  510.         move.b    d1,ReceivedCmd
  511.         bra    SecTalk        ;Sek.adr nach Talk
  512.  
  513. 2$        move.b    #ST_TIMEOUT,d0    ;Es erfolgte kein Listen/Talk
  514.         rts
  515.  
  516.  
  517. **
  518. ** IECIn - Ein Byte einlesen
  519. ** RÜckgabe: d1.b: Byte
  520. **
  521.  
  522. IECIn        tst.b    TalkerIsIEC    ;Talker am IEC-Kabel?
  523.         bne    IECByteIn
  524.         tst.b    TalkerActive    ;Wurde ein Gerät angesprochen?
  525.         beq    1$
  526.  
  527.         cmp.b    #CMD_DATA,ReceivedCmd
  528.         beq    DataIn
  529.  
  530. 1$        move.b    #ST_TIMEOUT,d0    ;Kein Talk bzw. kein CMD_DATA
  531.         clr.b    d1
  532.         rts
  533.  
  534.  
  535. **
  536. ** IECSetATN - ATN setzen (für Untalk)
  537. **
  538.  
  539. IECSetATN    tst.b    TalkerIsIEC    ;Nur bei IEC-Geräten etwas machen
  540.         beq    1$
  541.         CLOCK_LO
  542.         ATN_LO
  543. 1$        rts
  544.  
  545.  
  546. **
  547. ** IECRelATN - ATN wegnehmen
  548. **
  549.  
  550. IECRelATN    tst.b    IECIsOpen
  551.         beq    1$
  552.         ATN_HI
  553.         bsr    Wait20us
  554. 1$        rts
  555.  
  556.  
  557. **
  558. ** IECTurnaround - Talk-attention turn around
  559. **
  560.  
  561. IECTurnaround    tst.b    TalkerIsIEC    ;Nur bei IEC-Geräten etwas machen
  562.         beq    1$
  563.         move.l    a6,-(sp)
  564.         move.l    _SysBase,a6
  565.         JSRLIB    Disable
  566.         DATA_LO
  567.         bsr    Wait20us
  568.         ATN_HI
  569.         CLOCK_HI
  570.         WAIT_CLOCK_LO
  571.         bsr    Wait60us
  572.         JSRLIB    Enable
  573.         move.l    (sp)+,a6
  574. 1$        rts
  575.  
  576.  
  577. **
  578. ** IECRelease - System line release
  579. **
  580.  
  581. IECRelease    tst.b    IECIsOpen
  582.         beq    1$
  583.         LINE_RELEASE
  584. 1$        rts
  585.  
  586.  
  587. *
  588. * Listen
  589. * d0.b: Gerätenummer
  590. * d1.b: Funktion
  591. *
  592.  
  593. Listen        cmp.b    #8,d0        ;Gerät zwischen 8 und 11?
  594.         blo    ListenOther
  595.         cmp.b    #11,d0
  596.         bhi    ListenOther
  597.  
  598.         moveq    #0,d1        ;Ja, Zeiger auf Datenbereich holen
  599.         move.b    d0,d1
  600.         subq.b    #8,d1
  601.         move.l    (DrvTab,d1.w*4),a0
  602.         tst.b    drv_IsIEC(a0)    ;IEC-Gerät?
  603.         bne    ListenIEC
  604.         tst.l    drv_Lock(a0)    ;Nein, Verzeichnis vorhanden?
  605.         beq    ListenNotPr
  606.  
  607.         move.l    a0,ListenerData    ;Ja, Zeiger auf Datenbereich sichern
  608.         st.b    ListenerActive    ;Listener ist aktiv
  609.         clr.b    ListenerIsIEC
  610.         moveq    #ST_OK,d0
  611.         rts
  612.  
  613. ; Anderes Gerät außer 8..11
  614. ListenOther    tst.w    OtherIEC
  615.         beq    ListenNotPr
  616.  
  617. ; Listen über IEC-Kabel
  618. ListenIEC    move.l    a0,ListenerData    ;Zeiger auf Datenbereich sichern
  619.  
  620.         moveq    #$20,d1        ;Listen über Kabel senden
  621.         bsr    IECByteOutATN
  622.         cmp.b    #ST_NOTPRESENT,d0
  623.         beq    ListenNotPr
  624.         st.b    ListenerIsIEC    ;Gelungen, Listener ist aktiv
  625.         rts
  626.  
  627. ; Gerät nicht vorhanden
  628. ListenNotPr    move.b    #ST_NOTPRESENT,d0
  629.         clr.b    ListenerActive
  630.         clr.b    ListenerIsIEC
  631.         rts
  632.  
  633.  
  634. *
  635. * Talk
  636. * d0.b: Gerätenummer
  637. * d1.b: Funktion
  638. *
  639.  
  640. Talk        cmp.b    #8,d0        ;Gerät zwischen 8 und 11?
  641.         blo    TalkOther
  642.         cmp.b    #11,d0
  643.         bhi    TalkOther
  644.  
  645.         moveq    #0,d1        ;Ja, Zeiger auf Datenbereich holen
  646.         move.b    d0,d1
  647.         subq.b    #8,d1
  648.         move.l    (DrvTab,d1.w*4),a0
  649.         tst.b    drv_IsIEC(a0)    ;IEC-Gerät?
  650.         bne    TalkIEC
  651.         tst.l    drv_Lock(a0)    ;Nein, Verzeichnis vorhanden?
  652.         beq    TalkNotPr
  653.  
  654.         move.l    a0,TalkerData    ;Ja, Zeiger auf Datenbereich sichern
  655.         st.b    TalkerActive    ;Talker ist aktiv
  656.         clr.b    TalkerIsIEC
  657.         moveq    #ST_OK,d0
  658.         rts
  659.  
  660. ; Anderes Gerät außer 8..11
  661. TalkOther    tst.w    OtherIEC
  662.         beq    TalkNotPr
  663.  
  664. ; Talk über IEC-Kabel
  665. TalkIEC        move.l    a0,TalkerData    ;Zeiger auf Datenbereich sichern
  666.  
  667.         moveq    #$40,d1        ;Talk über Kabel senden
  668.         bsr    IECByteOutATN
  669.         cmp.b    #ST_NOTPRESENT,d0
  670.         beq    TalkNotPr
  671.         st.b    TalkerIsIEC    ;Gelungen, Talker ist aktiv
  672.         rts
  673.  
  674. ; Gerät nicht vorhanden
  675. TalkNotPr    move.b    #ST_NOTPRESENT,d0
  676.         clr.b    TalkerActive
  677.         clr.b    TalkerIsIEC
  678.         rts
  679.  
  680.  
  681. *
  682. * Unlisten
  683. * d0.b: Gerätenummer
  684. * d1.b: Funktion
  685. *
  686.  
  687. Unlisten    tst.b    ListenerIsIEC    ;Listener am IEC-Kabel?
  688.         beq    1$
  689.         bsr    IECByteOutATN    ;Ja, Unlisten über Kabel senden
  690.         bra    2$
  691.  
  692. 1$        moveq    #ST_OK,d0
  693. 2$        clr.b    ListenerActive    ;Gerät nicht mehr aktiv
  694.         clr.b    ListenerIsIEC
  695.         rts
  696.  
  697. *
  698. * Untalk
  699. * d0.b: Gerätenummer
  700. * d1.b: Funktion
  701. *
  702.  
  703. Untalk        tst.b    TalkerIsIEC    ;Talker am IEC-Kabel?
  704.         beq    1$
  705.         bsr    IECByteOutATN    ;Ja, Untalk über Kabel senden
  706.         bra    2$
  707.  
  708. 1$        moveq    #ST_OK,d0
  709. 2$        clr.b    TalkerActive    ;Gerät nicht mehr aktiv
  710.         clr.b    TalkerIsIEC
  711.         rts
  712.  
  713.  
  714. *
  715. * SecListen - Sekundäradresse nach Listen
  716. * d0.b: Sekundäradresse
  717. * d1.b: Befehlscode
  718. *
  719.  
  720. SecListen    cmp.b    #CMD_OPEN,d1
  721.         beq    SecListenOpen
  722.         cmp.b    #CMD_CLOSE,d1
  723.         beq    SecListenClose
  724.  
  725.         moveq    #ST_OK,d0
  726.         rts
  727.  
  728.  
  729. *
  730. * Open-Befehl: Auf Empfang des Dateinamens vorbereiten
  731. *
  732.  
  733. SecListenOpen    move.l    ListenerData,a0
  734.         move.l    #NameBuf,drv_NamePtr(a0)
  735.         moveq    #ST_OK,d0
  736.         rts
  737.  
  738.  
  739. *
  740. * Close-Befehl: Datei schließen
  741. *
  742.  
  743. SecListenClose    movem.l    a2/a4/a6,-(sp)
  744.         move.l    _DOSBase,a6
  745.         move.l    ListenerData,a4
  746.  
  747.         moveq    #0,d0        ;Zeiger auf FileHandle holen
  748.         move.b    SecAddr,d0
  749.         lea    drv_Handles(a4,d0.w*4),a2
  750.         move.l    (a2),d1        ;Datei schließen, wenn geöffnet
  751.         beq    1$
  752.         JSRLIB    Close
  753.         clr.l    (a2)
  754.  
  755. 1$        movem.l    (sp)+,a2/a4/a6
  756.         moveq    #ST_OK,d0
  757.         rts
  758.  
  759.  
  760. *
  761. * SecTalk - Sekundäradresse nach Talk
  762. * d0.b: Sekundäradresse
  763. * d1.b: Befehlscode
  764. *
  765.  
  766. SecTalk        cmp.b    #15,d0        ;Kanal 15 (Fehlerkanal)?
  767.         beq    SecTalk15
  768.  
  769.         moveq    #ST_OK,d0
  770.         rts
  771.  
  772.  
  773. *
  774. * Kanal 15: Fehlermeldung bereitstellen
  775. *
  776.  
  777. SecTalk15    move.l    TalkerData,a1
  778.         lea    ErrorTab,a0    ;Zeiger auf Fehlermeldung laden
  779.         moveq    #0,d0
  780.         move.b    drv_ErrorCode(a1),d0
  781.         move.l    (a0,d0.w*4),drv_ErrorPtr(a1)
  782.         move.b    #ERR_OK,drv_ErrorCode(a1) ;Fehlercode löschen
  783.         moveq    #ST_OK,d0
  784.         rts
  785.  
  786.  
  787. *
  788. * Byte nach Open-Befehl: Zeichen im Dateinamen speichern, bei EOI Datei öffnen
  789. * d0.b: Byte
  790. * d1.b: EOI-Flag
  791. *
  792.  
  793. OpenOut        cmp.b    #15,SecAddr    ;Kanal 15 (Kommandokanal)?
  794.         beq    1$
  795.  
  796.         move.l    ListenerData,a0    ;Nein, Zeichen speichern
  797.         move.l    drv_NamePtr(a0),a1
  798.         bsr    ConvFrom64    ;Zeichensatz wandeln
  799.         move.b    d0,(a1)+
  800.         move.l    a1,drv_NamePtr(a0)
  801.  
  802.         tst.b    d1        ;EOI: Datei öffnen
  803.         bmi    OpenFile
  804.  
  805. 1$        moveq    #ST_OK,d0
  806.         rts
  807.  
  808.  
  809. *
  810. * Dateiname nach Open-Befehl empfangen: Datei öffnen
  811. *
  812.  
  813. OpenFile    movem.l    d2-d4/a2/a4/a6,-(sp)
  814.         move.l    _DOSBase,a6
  815.         move.l    ListenerData,a4
  816.  
  817. ; Zeiger auf FileHandle nach a2 holen
  818.         moveq    #0,d0
  819.         move.b    SecAddr,d0
  820.         lea    drv_Handles(a4,d0.w*4),a2
  821.  
  822. ; Vorige Datei schließen, wenn noch offen
  823.         move.l    (a2),d1
  824.         beq    1$
  825.         JSRLIB    Close
  826.         clr.l    (a2)
  827. 1$
  828.  
  829. ; Erstes Zeichen des Dateinamens='$'? Dann Directory öffnen
  830.         cmp.b    #'$',NameBuf
  831.         beq    OpenDir
  832.  
  833. ; Erstes Zeichen des Dateinamens='#'? Dann "NO CHANNEL"
  834.         cmp.b    #'#',NameBuf
  835.         beq    OpenDirect
  836.  
  837. ; In das Verzeichnis des Laufwerks wechseln
  838.         move.l    drv_Lock(a4),d1
  839.         JSRLIB    CurrentDir
  840.         move.l    d0,d4        ;d4: Lock auf altes Verzeichnis
  841.  
  842. ; Dateinamen mit Nullbyte abschließen, Laufwerksbezeichnung entfernen
  843. ; und Dateityp ermitteln
  844.         move.l    #MODE_OLDFILE,FileMode ;Vorgaben
  845.         clr.w    FileIsSeq
  846.         clr.w    FileAppending
  847.  
  848.         move.l    drv_NamePtr(a4),a0
  849.         clr.b    (a0)
  850.  
  851.         lea    NameBuf,a0    ;Zuerst nach ':' suchen
  852.         move.l    a0,FileNamePtr
  853. OFColonLoop    tst.b    (a0)        ;Ende erreicht?
  854.         beq    OFNoColon
  855.         cmp.b    #':',(a0)+    ;Nein, ':' gefunden?
  856.         bne    OFColonLoop    ;Nein, weitersuchen
  857.  
  858.         move.l    a0,FileNamePtr    ;Ja, alles davor abschneiden
  859.  
  860. OFNoColon    move.l    FileNamePtr,a0    ;Dann nach ',' suchen
  861. OFCommaLoop1    tst.b    (a0)        ;Ende erreicht?
  862.         beq    OFNoComma
  863.         cmp.b    #',',(a0)+    ;Nein, ',' gefunden?
  864.         bne    OFCommaLoop1
  865.  
  866.         clr.b    -1(a0)        ;Ja, alles danach und inklusive abschneiden
  867.         move.b    (a0)+,d0    ;Dateityp lesen
  868.         cmp.b    #'s',d0        ;Sequentielle Datei?
  869.         bne    OFCommaLoop2
  870.         move.w    #-1,FileIsSeq    ;Ja, Flag setzen
  871.  
  872. OFCommaLoop2    tst.b    (a0)        ;Ende erreicht?
  873.         beq    OFNoComma
  874.         cmp.b    #',',(a0)+    ;Nein, ',' gefunden?
  875.         bne    OFCommaLoop2
  876.  
  877.         cmp.b    #'w',(a0)    ;Datei zum Schreiben öffnen?
  878.         bne    1$
  879.         move.l    #MODE_NEWFILE,FileMode
  880. 1$        cmp.b    #'r',(a0)    ;Datei zum Lesen öffnen?
  881.         bne    2$
  882.         move.l    #MODE_OLDFILE,FileMode
  883. 2$        cmp.b    #'a',(a0)    ;Datei zum Anhängen öffnen?
  884.         bne    3$
  885.         move.l    #MODE_OLDFILE,FileMode
  886.         move.w    #-1,FileAppending ;Ja, Flag setzen
  887. 3$
  888. OFNoComma
  889.  
  890. ; Bei Sek.adr 0 immer lesen, bei Sek.adr 1 immer schreiben
  891.         cmp.b    #0,SecAddr    ;Load?
  892.         bne    1$
  893.         move.l    #MODE_OLDFILE,FileMode
  894. 1$        cmp.b    #1,SecAddr    ;Save?
  895.         bne    2$
  896.         move.l    #MODE_NEWFILE,FileMode
  897. 2$
  898.  
  899. ; Nach Wildcards suchen, '*' durch '#?' ersetzen,
  900. ; Name nach NameBuf2 kopieren und Flag für Wildcard setzen
  901.         clr.w    FileIsWild    ;Vorgabe
  902.         move.l    FileNamePtr,a0
  903.         lea    NameBuf2,a1
  904. 10$        move.b    (a0)+,d0
  905.         beq    11$
  906.         cmp.b    #'*',d0
  907.         bne    12$
  908.         move.w    #'#?',(a1)+    ;'*' -> '#?'
  909.         move.w    #-1,FileIsWild
  910.         bra    11$        ;Danach alles abschneiden
  911. 12$        cmp.b    #'?',d0
  912.         bne    13$
  913.         move.b    #'?',(a1)+    ;'?' -> '?'
  914.         move.w    #-1,FileIsWild
  915.         bra    10$        ;Weitersuchen
  916. 13$        move.b    d0,(a1)+
  917.         bra    10$        ;Weitersuchen
  918.  
  919. 11$        clr.b    (a1)+
  920.  
  921. ; Eine neue Datei darf nicht mit Wildcards geöffnet werden,
  922. ; ansonsten nach der ersten passenden Datei suchen
  923.         tst.w    FileIsWild
  924.         beq    20$
  925.         cmp.l    #MODE_NEWFILE,FileMode
  926.         beq    OFSyn33
  927.         bsr    FindFirstFile
  928. 20$
  929.  
  930. ; Datei öffnen und erstes Zeichen lesen, wenn zum Lesen geöffnet
  931.         move.b    #ERR_OK,drv_ErrorCode(a4) ;Vorgabe: Alles OK
  932.  
  933.         move.l    #NameBuf2,d1
  934.         move.l    FileMode,d2
  935.         JSRLIB    Open
  936.         move.l    d0,(a2)
  937.         beq    OFNotFound
  938.  
  939.         tst.w    FileAppending    ;Datei zum Anhängen geöffnet?
  940.         beq    4$
  941.         move.l    (a2),d1        ;Ja, ans Ende gehen
  942.         moveq    #0,d2
  943.         move.l    #OFFSET_END,d3
  944.         JSRLIB    Seek
  945.         bra    OFDone
  946.  
  947. 4$        cmp.l    #MODE_NEWFILE,FileMode ;Neue Datei anlegen?
  948.         beq    5$
  949.         move.l    (a2),d1        ;Nein, erstes Zeichen lesen
  950.         JSRLIB    FGetC
  951.         move.b    d0,drv_ReadBuf(a4)
  952.         bra    OFDone
  953.  
  954. 5$        tst.w    FileIsSeq    ;Ja, bei sequentieller Datei E-Bit löschen
  955.         beq    7$
  956.         move.l    (a2),d1
  957.         JSRLIB    Close
  958.         move.l    FileNamePtr,d1
  959.         move.l    #FIBF_EXECUTE,d2
  960.         JSRLIB    SetProtection
  961.         move.l    FileNamePtr,d1
  962.         move.l    FileMode,d2
  963.         JSRLIB    Open
  964.         move.l    d0,(a2)
  965.         beq    OFNotFound
  966.         bra    OFDone
  967.  
  968. 7$        move.l    (a2),d1        ;Sonst E-Bit setzen
  969.         JSRLIB    Close
  970.         move.l    FileNamePtr,d1
  971.         moveq    #0,d2
  972.         JSRLIB    SetProtection
  973.         move.l    FileNamePtr,d1
  974.         move.l    FileMode,d2
  975.         JSRLIB    Open
  976.         move.l    d0,(a2)
  977.         beq    OFNotFound
  978.  
  979. ; In das ursprüngliche Verzeichnis wechseln
  980. OFDone        move.l    d4,d1
  981.         JSRLIB    CurrentDir
  982.  
  983.         movem.l    (sp)+,d2-d4/a2/a4/a6
  984.         moveq    #ST_OK,d0
  985.         rts
  986.  
  987. OFSyn33        move.b    #ERR_SYNTAX33,drv_ErrorCode(a4)
  988.         bra    OFDone
  989.  
  990. OFNotFound    move.b    #ERR_FILENOTFOUND,drv_ErrorCode(a4)
  991.         bra    OFDone
  992.  
  993.  
  994. *
  995. * Erste zum Muster passende Datei suchen
  996. * Muster in NameBuf2, Dateiname wird ebenfalls dorthin kopiert
  997. * Wenn das MatchFirst fehlschlägt, wird NameBuf2 nicht geändert
  998. *  und versucht, die Datei so zu öffnen
  999. *
  1000.  
  1001. FindFirstFile    lea    TheAnchor,a0
  1002.         clr.l    ap_BreakBits(a0)
  1003.         clr.l    ap_Strlen(a0)
  1004.  
  1005.     move.l    #NameBuf2,$180000
  1006.  
  1007.         move.l    #NameBuf2,d1
  1008.         move.l    #TheAnchor,d2
  1009.         JSRLIB    MatchFirst
  1010.         tst.l    d0
  1011.         bne    1$        ;Nicht gelungen, NameBuf2 nicht ändern
  1012.  
  1013.         lea    TheAnchor+ap_Info+fib_FileName,a0
  1014.         lea    NameBuf2,a1
  1015.         moveq    #63,d0
  1016. 2$        move.b    (a0)+,(a1)+    ;Sonst Name kopieren
  1017.         dbeq    d0,2$
  1018.  
  1019. 1$        move.l    #TheAnchor,d1
  1020.         JSRLIB    MatchEnd
  1021.         rts
  1022.  
  1023.  
  1024. *
  1025. * Directory wird geöffnet, temporäre Datei erstellen
  1026. *
  1027.  
  1028. ; Verzeichnis examinieren
  1029. OpenDir        move.l    drv_Lock(a4),d1
  1030.         move.l    #TheFIB,d2
  1031.         JSRLIB    Examine
  1032.         tst.l    d0
  1033.         beq    ODError
  1034.  
  1035. ; Gelungen, temp. Datei öffnen
  1036.         move.l    #TempFileName,d1
  1037.         move.l    #MODE_NEWFILE,d2
  1038.         JSRLIB    Open
  1039.         move.l    d0,d4        ;d4: FileHandle der temp. Datei
  1040.         beq    ODError
  1041.  
  1042. ; Directory-Titel erzeugen und schreiben
  1043.         lea    NameBuf,a0
  1044.         move.l    #$01040101,(a0)+ ;Ladeadresse und Verkettung
  1045.         clr.w    (a0)+        ;Laufwerksnummer (0) als Zeilennummer
  1046.         move.w    #$1222,(a0)+    ;RVS ON und '"'
  1047.  
  1048.         lea    TheFIB+fib_FileName,a1
  1049.         moveq    #15,d1        ;Max. 16 Zeichen Verzeichnisname wandeln
  1050. 1$        move.b    (a1)+,d0
  1051.         bsr    ConvTo64
  1052.         move.b    d0,(a0)+
  1053.         dbeq    d1,1$
  1054.         bne    2$
  1055.         subq.w    #1,a0        ;Den Rest mit Leerzeichen auffüllen
  1056. 3$        move.b    #' ',(a0)+
  1057.         dbra    d1,3$
  1058.         
  1059. 2$        move.w    #$2220,(a0)+    ;'" '
  1060.         move.l    #'00 2',(a0)+    ;ID und Formatkennzeichen
  1061.         move.w    #$4100,(a0)+    ;Abschließendes Nullbyte
  1062.  
  1063.         move.l    d4,d1        ;Zeile schreiben
  1064.         move.l    #NameBuf,d2
  1065.         moveq    #32,d3
  1066.         JSRLIB    Write
  1067.  
  1068. ; Schleife für alle Verzeichniseinträge
  1069. ; Nächsten Eintrag holen
  1070. ODLoop        move.l    drv_Lock(a4),d1
  1071.         move.l    #TheFIB,d2
  1072.         JSRLIB    ExNext
  1073.         tst.l    d0
  1074.         beq    ODLoopEnd
  1075.  
  1076. ; Directory-Zeile erzeugen und schreiben
  1077.         lea    NameBuf,a0    ;Zeile mit Leerzeichen löschen
  1078.         moveq    #30,d1
  1079. 20$        move.b    #' ',(a0)+
  1080.         dbra    d1,20$
  1081.         clr.b    (a0)        ;und mit Nullbyte abschließen
  1082.  
  1083.         lea    NameBuf,a0
  1084.         move.w    #$0101,(a0)+    ;Verkettung
  1085.         move.l    TheFIB+fib_Size,d0 ;Größe in Blocks berechnen
  1086.         add.l    #254,d0
  1087.         divu.w    #254,d0
  1088.         rol.w    #8,d0        ;MSB und LSB vertauschen
  1089.         move.w    d0,(a0)+    ;Als Zeilennummer eintragen
  1090.         rol.w    #8,d0        ;Bytefolge korrigieren
  1091.         addq.l    #1,a0        ;Ein Leerzeichen mindestens
  1092.         cmp.w    #10,d0        ;Kleiner als 10?
  1093.         bhs    10$
  1094.         addq.l    #1,a0        ;Ja, ein Leerzeichen dazunehmen
  1095. 10$        cmp.w    #100,d0        ;Kleiner als 100?
  1096.         bhs    11$
  1097.         addq.l    #1,a0        ;Ja, noch ein Leerzeichen dazunehmen
  1098. 11$        move.b    #'"',(a0)+
  1099.  
  1100.         move.l    a0,-(sp)
  1101.         lea    TheFIB+fib_FileName,a1
  1102.         moveq    #15,d1        ;Max. 16 Zeichen Dateiname wandeln
  1103. 1$        move.b    (a1)+,d0
  1104.         bsr    ConvTo64
  1105.         move.b    d0,(a0)+
  1106.         dbeq    d1,1$
  1107.         bne    2$
  1108.         subq.w    #1,a0        ;Nullbyte überschreiben
  1109. 2$        move.b    #'"',(a0)+    ;Mit '"' abschließen
  1110.         move.l    (sp)+,a0
  1111.         lea    18(a0),a0    ;An festgelegter Spalte weitermachen
  1112.  
  1113.         tst.l    TheFIB+fib_DirEntryType ;Typ ermitteln und eintragen
  1114.         bmi    ODIsFile
  1115.         move.l    #'DIR ',(a0)+
  1116.         bra    ODLineEnd
  1117. ODIsFile    btst    #FIBB_EXECUTE,TheFIB+fib_Protection+3
  1118.         beq    ODIsPRG
  1119.         move.l    #'SEQ ',(a0)+
  1120.         bra    ODLineEnd
  1121. ODIsPRG        move.l    #'PRG ',(a0)+
  1122.  
  1123. ODLineEnd    move.l    d4,d1        ;Zeile schreiben
  1124.         move.l    #NameBuf,d2
  1125.         moveq    #32,d3
  1126.         JSRLIB    Write
  1127.         bra    ODLoop
  1128.  
  1129. ; Abschlußzeile mit "BLOCKS FREE." erzeugen und schreiben
  1130. ODLoopEnd    lea    NameBuf,a0    ;Zeile mit Leerzeichen löschen
  1131.         moveq    #28,d1
  1132. 20$        move.b    #' ',(a0)+
  1133.         dbra    d1,20$
  1134.         clr.w    (a0)+        ;Und mit drei Nullbytes abschließen
  1135.         clr.b    (a0)
  1136.  
  1137.         lea    NameBuf,a0
  1138.         move.w    #$0101,(a0)+    ;Verkettung
  1139.         clr.w    (a0)+        ;Anzahl freier Blöcke (0)
  1140.         move.l    #'BLOC',(a0)+
  1141.         move.l    #'KS F',(a0)+
  1142.         move.l    #'REE.',(a0)+
  1143.  
  1144.         move.l    d4,d1        ;Zeile schreiben
  1145.         move.l    #NameBuf,d2
  1146.         moveq    #32,d3
  1147.         JSRLIB    Write
  1148.  
  1149. ; Temp. Datei schließen
  1150.         move.l    d4,d1
  1151.         JSRLIB    Close
  1152.  
  1153. ; Und wieder zum Lesen öffnen und das erste Zeichen lesen
  1154.         move.l    #TempFileName,d1
  1155.         move.l    #MODE_OLDFILE,d2
  1156.         JSRLIB    Open
  1157.         move.l    d0,(a2)
  1158.         beq    ODError
  1159.  
  1160.         move.l    d0,d1
  1161.         JSRLIB    FGetC
  1162.         move.b    d0,drv_ReadBuf(a4)
  1163.  
  1164. ODError        movem.l    (sp)+,d2-d4/a2/a4/a6
  1165.         moveq    #ST_OK,d0
  1166.         rts
  1167.  
  1168.  
  1169. *
  1170. * Direktzugriffskanal wird geöffnet, Fehlermeldung
  1171. *
  1172.  
  1173. OpenDirect    move.b    #ERR_NOCHANNEL,drv_ErrorCode(a4)
  1174.         movem.l    (sp)+,d2-d4/a2/a4/a6
  1175.         moveq    #ST_OK,d0
  1176.         rts
  1177.  
  1178.  
  1179. *
  1180. * Byte nach Data-Befehl: Zeichen in Datei schreiben
  1181. * d0.b: Byte
  1182. * d1.b: EOI-Flag
  1183. *
  1184.  
  1185. DataOut        cmp.b    #15,SecAddr    ;Kanal 15 (Kommandokanal)?
  1186.         beq    2$
  1187.  
  1188.         movem.l    d2/a2/a4/a6,-(sp)
  1189.         move.l    _DOSBase,a6
  1190.         move.l    ListenerData,a4
  1191.         moveq    #0,d2
  1192.         move.b    d0,d2        ;d2: Byte
  1193.  
  1194.         moveq    #0,d0        ;Zeiger auf FileHandle holen
  1195.         move.b    SecAddr,d0
  1196.         lea    drv_Handles(a4,d0.w*4),a2
  1197.         move.l    (a2),d1        ;Datei geöffnet?
  1198.         beq    1$
  1199.  
  1200.         JSRLIB    FPutC        ;Zeichen schreiben
  1201.         tst.l    d0
  1202.         bmi    1$
  1203.  
  1204.         moveq    #ST_OK,d0
  1205.         movem.l    (sp)+,d2/a2/a4/a6
  1206.         rts
  1207.  
  1208. 1$        move.b    #ST_TIMEOUT,d0    ;Fehler aufgetreten
  1209.         movem.l    (sp)+,d2/a2/a4/a6
  1210.         rts
  1211.  
  1212. 2$        moveq    #ST_OK,d0
  1213.         rts
  1214.  
  1215.  
  1216. *
  1217. * Zeichen aus Datenkanal lesen
  1218. * RÜckgabe: d1.b: Byte
  1219. *
  1220.  
  1221. DataIn        cmp.b    #15,SecAddr    ;Kanal 15 (Fehlerkanal)?
  1222.         beq    Channel15In
  1223.  
  1224.         movem.l    d2/a2/a4/a6,-(sp)
  1225.         move.l    _DOSBase,a6
  1226.         move.l    TalkerData,a4
  1227.  
  1228.         moveq    #0,d0        ;Zeiger auf FileHandle holen
  1229.         move.b    SecAddr,d0
  1230.         lea    drv_Handles(a4,d0.w*4),a2
  1231.         move.l    (a2),d1        ;Datei geöffnet?
  1232.         beq    1$
  1233.  
  1234.         move.b    drv_ReadBuf(a4),d2 ;Zeichen aus dem Puffer holen
  1235.  
  1236.         JSRLIB    FGetC        ;Nächstes Zeichen lesen
  1237.         move.b    d0,drv_ReadBuf(a4) ;und Puffern
  1238.         tst.l    d0
  1239.         bmi    2$        ;EOF? Dann Status setzen
  1240.  
  1241.         moveq    #ST_OK,d0
  1242.         bra    3$
  1243. 2$        move.b    #ST_EOF,d0
  1244. 3$        move.b    d2,d1        ;Zeichen wieder holen
  1245.         movem.l    (sp)+,d2/a2/a4/a6
  1246.         rts
  1247.  
  1248. 1$        move.b    #ST_READ_TIMEOUT,d0    ;Fehler aufgetreten
  1249.         clr.b    d1
  1250.         movem.l    (sp)+,d2/a2/a4/a6
  1251.         rts
  1252.  
  1253.  
  1254. *
  1255. * Aus Kanal 15 lesen
  1256. *
  1257.  
  1258. Channel15In    move.l    TalkerData,a0
  1259.         move.l    drv_ErrorPtr(a0),a1 ;Nächstes Zeichen holen
  1260.         move.b    (a1)+,d1
  1261.         cmp.b    #13,d1        ;CR (letztes Zeichen)?
  1262.         beq    1$
  1263.         move.l    a1,drv_ErrorPtr(a0) ;Nein, Zeiger merken
  1264.         moveq    #ST_OK,d0
  1265.         rts
  1266.  
  1267. 1$        move.b    #ST_EOF,d0    ;Letztes Zeichen: EOF
  1268.         move.l    #OKText,drv_ErrorPtr(a0) ;Falls jemand noch mehr will...
  1269.         rts
  1270.  
  1271.  
  1272. *
  1273. * Umwandlung PETSCII->ASCII
  1274. * Zeichen in d0
  1275. *
  1276.  
  1277. ConvFrom64    cmp.b    #'/',d0
  1278.         beq    3$
  1279.         cmp.b    #'A',d0
  1280.         blo    1$
  1281.         cmp.b    #'Z',d0
  1282.         bhi    2$
  1283.         or.b    #$20,d0        ;Großbuchstaben
  1284.         rts
  1285. 2$        cmp.b    #'a',d0
  1286.         blo    1$
  1287.         cmp.b    #'z',d0
  1288.         bhi    1$
  1289.         and.b    #$df,d0        ;Kleinbuchstaben
  1290. 1$        rts
  1291. 3$        tst.w    MapSlash
  1292.         beq    1$
  1293.         move.b    #'\\',d0
  1294.         rts
  1295.  
  1296.  
  1297. *
  1298. * Umwandlung ASCII->PETSCII
  1299. * Zeichen in d0
  1300. *
  1301.  
  1302. ConvTo64    cmp.b    #'\\',d0
  1303.         beq    3$
  1304.         cmp.b    #'A',d0
  1305.         blo    1$
  1306.         cmp.b    #'Z',d0
  1307.         bhi    2$
  1308.         or.b    #$20,d0        ;Großbuchstaben
  1309.         rts
  1310. 2$        cmp.b    #'a',d0
  1311.         blo    1$
  1312.         cmp.b    #'z',d0
  1313.         bhi    1$
  1314.         and.b    #$df,d0        ;Kleinbuchstaben
  1315. 1$        rts
  1316. 3$        tst.w    MapSlash
  1317.         beq    1$
  1318.         move.b    #'/',d0
  1319.         rts
  1320.  
  1321.  
  1322. *
  1323. * Byte mit ATN über IEC-Kabel senden
  1324. * d0.b: Gerätenummer
  1325. * d1.b: Funktion
  1326. *
  1327.  
  1328. IECByteOutATN    tst.b    IECIsOpen
  1329.         bne    1$
  1330.         move.b    #ST_NOTPRESENT,d0
  1331.         rts
  1332.  
  1333. 1$        movem.l    d2/d7/a6,-(sp)
  1334.         move.b    d0,d2
  1335.         or.b    d1,d2        ;d2: Auszugebendes Byte
  1336.  
  1337.         move.l    _SysBase,a6
  1338.         JSRLIB    Disable
  1339.  
  1340.         DATA_HI
  1341.         ATN_LO
  1342.         bra    IECByteOutSec2    ;ATN response abwarten und Byte ausgeben
  1343.  
  1344.  
  1345. *
  1346. * Sekundäradresse über IEC-Kabel senden
  1347. * d0.b: Sekundäradresse
  1348. *
  1349.  
  1350. IECByteOutSec    tst.b    IECIsOpen
  1351.         bne    1$
  1352.         move.b    #ST_NOTPRESENT,d0
  1353.         rts
  1354.  
  1355. 1$        movem.l    d2/d7/a6,-(sp)
  1356.         move.b    d0,d2        ;d2: Auszugebendes Byte
  1357.  
  1358.         move.l    _SysBase,a6
  1359.         JSRLIB    Disable
  1360.  
  1361. IECByteOutSec2    CLOCK_LO
  1362.         DATA_HI
  1363.         bsr    Wait1ms        ;Max ATN response abwarten
  1364.         moveq    #0,d1        ;Kein EOI
  1365.         bra    IECByteOut2    ;Byte ausgeben
  1366.  
  1367.  
  1368. *
  1369. * Byte über IEC-Kabel senden
  1370. * d0.b: Byte
  1371. * d1.b: EOI-Flag
  1372. *
  1373.  
  1374. IECByteOut    tst.b    IECIsOpen
  1375.         bne    1$
  1376.         move.b    #ST_NOTPRESENT,d0
  1377.         rts
  1378.  
  1379. 1$        movem.l    d2/d7/a6,-(sp)
  1380.         move.b    d0,d2        ;d2: Auszugebendes Byte
  1381.  
  1382.         move.l    _SysBase,a6
  1383.         JSRLIB    Disable
  1384.  
  1385. ; Übertragung einleiten
  1386. IECByteOut2    move.b    d1,d7        ;d7: EOI-Flag
  1387.         DATA_HI
  1388.         GET_DATA_CLOCK        ;Data bleibt high -> Device not present
  1389.         bcs    IBODevNotPr
  1390.         CLOCK_HI        ;Talker ready
  1391.  
  1392.         WAIT_DATA_HI        ;Warten auf Listener ready for data
  1393.  
  1394.         tst.b    d7        ;EOI?
  1395.         bpl    1$
  1396.  
  1397.         WAIT_DATA_LO        ;Ja, EOI-Handshake abwarten
  1398.         WAIT_DATA_HI
  1399.  
  1400. 1$        CLOCK_LO        ;Talker sending
  1401.  
  1402.         bsr    Wait40us    ;Wichtige Verzögerung, aber wozu?
  1403.  
  1404. ; 8 Bits übertragen
  1405.         moveq    #7,d7        ;d7: Bitzähler
  1406. IBOBitLoop    GET_DATA_CLOCK        ;Data low -> Time out
  1407.         bcc    IBOTimeOut
  1408.  
  1409.         lsr.b    #1,d2        ;Nächstes Bit holen
  1410.         bcc    1$        ;und ausgeben
  1411.         DATA_HI
  1412.         bra    2$
  1413. 1$        DATA_LO
  1414. 2$
  1415.         bsr    Wait40us    ;Bit set-up talker delay
  1416.  
  1417.         CLOCK_HI        ;Data valid
  1418.  
  1419.         bsr    Wait20us    ;Data valid delay
  1420.  
  1421.         DATA_HI
  1422.         CLOCK_LO
  1423.  
  1424.         dbra    d7,IBOBitLoop    ;Nächstes Bit
  1425.  
  1426. ; 1ms auf Bestätigung warten
  1427.         bsr    Start1ms    ;Timer starten
  1428.  
  1429. IBODACLoop    bsr    TimerDoneQ    ;Timer abgelaufen?
  1430.         bne    IBOTimeOut    ;Ja, dann Time out
  1431.         GET_DATA_CLOCK        ;Auf Listener data accepted warten
  1432.         bcs    IBODACLoop
  1433.  
  1434. ; Alles OK
  1435.         moveq    #ST_OK,d0
  1436.         bra    IBODone
  1437.  
  1438. ; Fehlerbehandlung
  1439. IBODevNotPr    LINE_RELEASE
  1440.         move.b    #ST_NOTPRESENT,d0
  1441.         bra    IBODone
  1442.  
  1443. IBOTimeOut    LINE_RELEASE
  1444.         move.b    #ST_TIMEOUT,d0
  1445.  
  1446. IBODone        JSRLIB    Enable
  1447.  
  1448.         movem.l    (sp)+,a6/d2/d7
  1449.         rts
  1450.  
  1451.  
  1452. *
  1453. * Byte über IEC-Kabel empfangen
  1454. * Rückgabe: d1.b: Empfangenes Byte
  1455. *
  1456.  
  1457. IECByteIn    tst.b    IECIsOpen
  1458.         bne    1$
  1459.         move.b    #ST_NOTPRESENT,d0
  1460.         rts
  1461.  
  1462. 1$        movem.l    d2/d3/d7/a6,-(sp)
  1463.         moveq    #ST_OK,d3    ;d3: Status
  1464.         move.l    _SysBase,a6
  1465.         JSRLIB    Disable
  1466.  
  1467.         CLOCK_HI
  1468.         WAIT_CLOCK_HI
  1469.  
  1470. ; Auf Beginn der Übertragung warten
  1471.         bsr    Start250us    ;Timer starten
  1472.         DATA_HI            ;Listener ready for data
  1473.  
  1474. IBIWaitTalker    bsr    TimerDoneQ    ;Timer abgelaufen?
  1475.         bne    IBIEOI        ;Ja, EOI empfangen
  1476.         GET_DATA_CLOCK        ;Warten auf talker sending
  1477.         bmi    IBIWaitTalker
  1478.         bra    IBIReceive
  1479.  
  1480. ; EOI empfangen, Handshake senden und erneut auf Beginn warten
  1481. IBIEOI        move.b    #ST_EOF,d3
  1482.         DATA_LO            ;EOI handshake
  1483.         CLOCK_HI
  1484.         bsr    Wait60us    ;EOI response hold time
  1485.  
  1486.         bsr    Start250us    ;Timer starten
  1487.         DATA_HI            ;Listener ready for data
  1488.  
  1489. IBIWaitTalker2    bsr    TimerDoneQ    ;Timer abgelaufen?
  1490.         bne    IBITimeOut    ;Ja, dann Time out
  1491.         GET_DATA_CLOCK        ;Warten auf talker sending
  1492.         bmi    IBIWaitTalker2
  1493.  
  1494. ; 8 Bits empfangen
  1495. IBIReceive    moveq    #7,d7        ;d7: Bitzähler
  1496.         moveq    #0,d2        ;d2: Empfangenes Byte
  1497.  
  1498. IBIBitLoop    WAIT_CLOCK_HI        ;Auf Data valid warten
  1499.         roxr.b    #1,d2        ;Datenbit holen
  1500.         WAIT_CLOCK_LO
  1501.         dbra    d7,IBIBitLoop
  1502.  
  1503. ; Empfang bestätigen
  1504.         DATA_LO            ;Listener data accepted
  1505.         btst    #6,d3        ;EOI empfangen?
  1506.         beq    IBIDone
  1507.         LINE_RELEASE        ;Ja, Leitung freigeben
  1508.         bra    IBIDone
  1509.  
  1510. ; Fehlerbehandlung
  1511. IBITimeOut    or.b    #ST_READ_TIMEOUT,d3
  1512.         LINE_RELEASE
  1513.  
  1514. IBIDone        move.b    d3,d0        ;Status holen
  1515.         move.b    d2,d1        ;Byte holen
  1516.         JSRLIB    Enable
  1517.         movem.l    (sp)+,d2/d3/d7/a6
  1518.         rts
  1519.  
  1520.  
  1521. *
  1522. * 20µs/40µs/60µs/1ms warten
  1523. *
  1524.  
  1525. ; Timer auf 20µs setzen
  1526. Wait20us    move.l    CiaControlReg,a0
  1527.         and.b    #$80,(a0)
  1528.         move.l    CiaTimerReg,a0
  1529.         move.b    #14,(a0)
  1530.         move.b    #0,$100(a0)
  1531.         bra    StartTimer
  1532.  
  1533. ; Timer auf 40µs setzen
  1534. Wait40us    move.l    CiaControlReg,a0
  1535.         and.b    #$80,(a0)
  1536.         move.l    CiaTimerReg,a0
  1537.         move.b    #29,(a0)
  1538.         move.b    #0,$100(a0)
  1539.         bra    StartTimer
  1540.  
  1541. ; Timer auf 60µs setzen
  1542. Wait60us    move.l    CiaControlReg,a0
  1543.         and.b    #$80,(a0)
  1544.         move.l    CiaTimerReg,a0
  1545.         move.b    #43,(a0)
  1546.         move.b    #0,$100(a0)
  1547.         bra    StartTimer
  1548.  
  1549. ; Timer auf 1ms setzen
  1550. Wait1ms        move.l    CiaControlReg,a0
  1551.         and.b    #$80,(a0)
  1552.         move.l    CiaTimerReg,a0
  1553.         move.b    #$cc,(a0)
  1554.         move.b    #2,$100(a0)
  1555.         move.l    CiaControlReg,a0
  1556.  
  1557. ; Timer anwerfen (One-Shot) und auf Ablauf warten
  1558. StartTimer    move.l    a6,-(sp)
  1559.         move.l    _CiaBase,a6
  1560.  
  1561.         move.b    WhichTimerMask,d0
  1562.         JSRLIB    SetICR
  1563.  
  1564.         move.l    CiaControlReg,a0
  1565.         move.b    #CIACRAF_LOAD|CIACRAF_RUNMODE|CIACRAF_START,(a0)
  1566.  
  1567. 1$        moveq    #0,d0
  1568.         JSRLIB    SetICR
  1569.         and.b    WhichTimerMask,d0
  1570.         beq    1$
  1571.  
  1572.         move.l    (sp)+,a6
  1573.         rts
  1574.  
  1575.  
  1576. *
  1577. * Timer starten, 1ms/250µs
  1578. *
  1579.  
  1580. Start1ms    move.l    a6,-(sp)
  1581.         move.l    _CiaBase,a6
  1582.         move.l    CiaControlReg,a0
  1583.         and.b    #$80,(a0)
  1584.  
  1585.         move.l    CiaTimerReg,a0
  1586.         move.b    #$cc,(a0)
  1587.         move.b    #2,$100(a0)
  1588.  
  1589.         move.b    WhichTimerMask,d0
  1590.         JSRLIB    SetICR
  1591.  
  1592.         move.l    CiaControlReg,a0
  1593.         or.b    #CIACRAF_LOAD|CIACRAF_RUNMODE|CIACRAF_START,(a0)
  1594.         move.l    (sp)+,a6
  1595.         rts
  1596.  
  1597. Start250us    move.l    a6,-(sp)
  1598.         move.l    _CiaBase,a6
  1599.         move.l    CiaControlReg,a0
  1600.         and.b    #$80,(a0)
  1601.  
  1602.         move.l    CiaTimerReg,a0
  1603.         move.b    #$b3,(a0)
  1604.         move.b    #0,$100(a0)
  1605.  
  1606.         move.b    WhichTimerMask,d0
  1607.         JSRLIB    SetICR
  1608.  
  1609.         move.l    CiaControlReg,a0
  1610.         or.b    #CIACRAF_LOAD|CIACRAF_RUNMODE|CIACRAF_START,(a0)
  1611.         move.l    (sp)+,a6
  1612.         rts
  1613.  
  1614.  
  1615. *
  1616. * Timer abgelaufen?
  1617. * bne: Ja
  1618. *
  1619.  
  1620. TimerDoneQ    move.l    a6,-(sp)
  1621.         move.l    _CiaBase,a6
  1622.         moveq    #0,d0
  1623.         JSRLIB    SetICR
  1624.         and.b    WhichTimerMask,d0
  1625.         move.l    (sp)+,a6
  1626.         tst.b    d0
  1627.         rts
  1628.  
  1629.  
  1630. *
  1631. * Dummy-Timer-Interrupt-Routine
  1632. *
  1633.  
  1634. IntTimer    moveq    #0,d0
  1635.         rts
  1636.  
  1637.  
  1638. **
  1639. ** Konstanten
  1640. **
  1641.  
  1642. ; Tabelle für Fehlermeldungen (Index: ErrorCode)
  1643.         CNOP    0,4
  1644. ErrorTab    dc.l    OKText
  1645.         dc.l    StartupText
  1646.         dc.l    FileNotFText
  1647.         dc.l    NoChannelText
  1648.         dc.l    Syntax33Text
  1649.  
  1650. ; Fehlertexte
  1651. OKText        dc.b    "00, OK,00,00",13
  1652. StartupText    dc.b    "73,CBM DOS V2.6 1541,00,00",13
  1653. FileNotFText    dc.b    "62,FILE NOT FOUND,00,00",13
  1654. NoChannelText    dc.b    "70,NO CHANNEL,00,00",13
  1655. Syntax33Text    dc.b    "33,SYNTAX ERROR,00,00",13
  1656.  
  1657. ; Tabelle mit Zeigern auf die Laufwerks-Datenstrukturen
  1658.         CNOP    0,4
  1659. DrvTab        dc.l    Drv8Data
  1660.         dc.l    Drv9Data
  1661.         dc.l    Drv10Data
  1662.         dc.l    Drv11Data
  1663.  
  1664. ; Name der temporären Datei für das Directory
  1665. TempFileName    dc.b    "T:Frodo$File",0
  1666.  
  1667. ; Name für AllocMiscResource
  1668. ParPortName    dc.b    "Frodo Parallel Port",0
  1669.  
  1670. ; Name des Timer-Interrupts
  1671. TimerIntName    dc.b    "Frodo Timer Int",0
  1672.         CNOP    0,4
  1673.  
  1674.  
  1675. **
  1676. ** Initialisierte Daten
  1677. **
  1678.  
  1679.         SECTION    "DATA",DATA
  1680.  
  1681. TimerInterrupt    dc.l    0,0
  1682.         dc.b    NT_INTERRUPT,0
  1683.         dc.l    TimerIntName
  1684.         dc.l    0
  1685.         dc.l    IntTimer
  1686.  
  1687.  
  1688. **
  1689. ** Nicht initialisierte Daten
  1690. **
  1691.  
  1692.         SECTION    "BSS",BSS
  1693.  
  1694. ; Global
  1695. ListenerActive    ds.b    1    ;Flag: Listener angewählt, ListenerData ist gültig
  1696. ListenerIsIEC    ds.b    1    ;Flag: Aktiver Listener hängt am IEC-Kabel (impliziert ListenerActive)
  1697. TalkerActive    ds.b    1    ;Flag: Talker angewählt, TalkerData ist gültig
  1698. TalkerIsIEC    ds.b    1    ;Flag: Aktiver Talker hängt am IEC-Kabel (impliziert TalkerActive)
  1699.  
  1700. Listening    ds.b    1    ;Flag: Letzter ATN-Befehl war Listen (für SecListen/SecTalk-Unterscheidung)
  1701. SecAddr        ds.b    1    ;Aktuelle Sekundäradresse ($0x)
  1702. ReceivedCmd    ds.b    1    ;Empfangener Befehlscode ($x0)
  1703.  
  1704. IECIsOpen    ds.b    1    ;Flag: Timer und Port belegt, IEC-Kabel kann benutzt werden
  1705.  
  1706. WhichTimer    ds.b    1    ;Welcher Timer wurde belegt? (0: Timer A, 1: Timer B)
  1707. WhichTimerMask    ds.b    1    ;Dto. als Bit-Maske für ICR
  1708.  
  1709.         CNOP    0,4
  1710. CiaTimerReg    ds.l    1    ;Zeiger auf Cia-Timer-Register
  1711. CiaControlReg    ds.l    1
  1712.  
  1713. ListenerData    ds.l    1    ;Zeiger auf Struktur des aktiven Listeners
  1714. TalkerData    ds.l    1    ;Zeiger auf Struktur des aktiven Talkers
  1715.  
  1716. FileNamePtr    ds.l    1    ;Zeiger auf Dateinamen für OpenFile
  1717. FileMode    ds.l    1    ;Zugriffsmodus für OpenFile
  1718. FileIsSeq    ds.w    1    ;Flag: Sequentielle Datei eröffnen
  1719. FileAppending    ds.w    1    ;Flag: Daten an Datei anhängen
  1720. FileIsWild    ds.w    1    ;Flag: Wildcards gefunden
  1721.  
  1722. ; Datenstruktur pro Laufwerk
  1723.         CNOP    0,4
  1724. Drv8Data    ds.b    drv_SIZEOF
  1725. Drv9Data    ds.b    drv_SIZEOF
  1726. Drv10Data    ds.b    drv_SIZEOF
  1727. Drv11Data    ds.b    drv_SIZEOF
  1728.  
  1729. ; Puffer für die Verzeichnisse der 4 Laufwerke
  1730. Dir8        ds.b    256
  1731. Dir9        ds.b    256
  1732. Dir10        ds.b    256
  1733. Dir11        ds.b    256
  1734.  
  1735. ; Puffer für Dateinamen
  1736. NameBuf        ds.b    64
  1737. NameBuf2    ds.b    64
  1738.  
  1739. ; Struktur für MatchFirst
  1740.         CNOP    0,4
  1741. TheAnchor    ds.b    ap_SIZEOF
  1742.  
  1743. ; Einstellungen
  1744. Drv8IsIEC    ds.w    1
  1745. Drv9IsIEC    ds.w    1
  1746. Drv10IsIEC    ds.w    1
  1747. Drv11IsIEC    ds.w    1
  1748. OtherIEC    ds.w    1
  1749. MapSlash    ds.w    1
  1750.  
  1751.         CNOP    0,4
  1752. TheFIB        ds.b    fib_SIZEOF    ;FileInfoBlock
  1753.  
  1754.         END
  1755.